<?php
/**
 * Theme.php
 *
 * @category    Madoqua
 * @package     Module
 * @subpackage  Theme
 */

/** zend config xml */
require_once 'Zend/Config/Xml.php';

/**
 * Theme_Theme
 *
 * @category    Madoqua
 * @package     Module
 * @subpackage  Theme
 */
class Theme_Theme
{
    /**
     * dir modifieds
     *
     * @var array
     */
    protected static $_dirModifieds = array();
    
    /**
     * get a theme
     *
     * @param string $key
     * @return object|bool
     */
    public static function get($key = null)
    {
        if ($key == null) {
            $key = Madoqua_Application::getConfiguration()->theme->active;
        }

        $config = self::getConfig($key);
        //find the config for the theme

        if ($config === false) {
            return false;
        }
        //find theme (or not)

        $theme = new stdClass;
        $theme->key = $key;
        $theme->config = $config;
        $theme->userConfig = self::getUserConfig($key);
        //build the theme as a stdClass object

        return $theme;
        //and return it like a proper dikdik
    }

    /**
     * get a list of themes
     *
     * @return array
     */
    public static function getList()
    {
        $directory = Madoqua_Application::getDataDirectory() . DIRECTORY_SEPARATOR . 'themes';
        //the directory that has the themes
        $iterator = new DirectoryIterator($directory);
        //iterator over that directory

        $themes = array();
        //array to be filled with themes

        foreach($iterator as $subdir) {
            if ($subdir->isDir() && !$subdir->isDot()) {
                $key = (string) $subdir;
                $themes[$key] = new stdClass();
                $themes[$key]->key = $key;
                //a bit double, but hey
            }
        }
        //fill $themes with all subdirs in the theme directory

        foreach($themes as $key => $theme) {
            $themes[$key] = self::get($key);
            if ($themes[$key] === false) {
                //no config found, this dir isn't a proper theme dir
                unset($themes[$key]);
            }
        }
        //have $themes filled only with proper themes

        return $themes;
    }
    
    /**
     * get a list of theme names (without config, etc.)
     *
     * @return array
     */
    public static function getNameList()
    {
        $directory = Madoqua_Application::getDataDirectory() . DIRECTORY_SEPARATOR . 'themes';
        //the directory that has the themes
        $iterator = new DirectoryIterator($directory);
        //iterator over that directory

        $themes = array();
        //array to be filled with themes

        foreach($iterator as $subdir) {
            if ($subdir->isDir() && !$subdir->isDot() && $subdir->getFilename() != 'config') {
                //ignore 'config'
                $themes[] = (string) $subdir;
            }
        }
        //fill $themes with all subdirs in the theme directory

        return $themes;
        
    }

    /**
     * get the theme config for a certain theme
     *
     * @param string $name
     * @return Zend_Config_Xml|bool
     */
    public static function getConfig($name)
    {
        $directory = Madoqua_Application::getDataDirectory() . DIRECTORY_SEPARATOR  . 'themes/';
        $directory .= $name . '/';
        //the directory that has the theme

        $file = $directory . 'theme.xml';
        //theme config file

        if (!file_exists($file)) {
            //theme file not found
            return false;
        }

        return Madoqua_Cache_Config::get($file);
        //return the proper config file
    }

    /**
     * get the user settings for a certain theme
     *
     * @param string $name
     * @return Zend_Config_Xml|bool
     */
    public static function getUserConfig($name)
    {
        $themeConfig = self::getConfig($name);
        //get theme config
        if ($themeConfig === false) {
            return false;
        }
        //theme doesn't exist/doesn't have config

        $file = Madoqua_Application::getDataDirectory() . DIRECTORY_SEPARATOR  . 'themes/config/';
        $file .= $name . '.xml';
        //theme config file

        if (!file_exists($file)) {
            //config file doesn't exist
            return $themeConfig->config;
            //return original config from theme file
        } else {
            $userConfig = Madoqua_Cache_Config::get($file);
            //user specified settings
            return $themeConfig->config->merge($userConfig);
            //return the original config,
            //but merged with the overridden values from the user config
        }


    }

    /**
     * save the user config for a theme
     *
     * @param string $name
     * @param array $values
     * @return bool
     */
    public static function saveUserConfig($name, $values)
    {
        $modelLoader = Zend_Controller_Action_HelperBroker::getStaticHelper('modelLoader');
        $modelLoader->load('BlogAdmin_Config');
        //load the blogadmin config model that allows config parsing

        $config = BlogAdmin_Config::fromArray($values);

        $file = Madoqua_Application::getDataDirectory() . DIRECTORY_SEPARATOR .  'themes/config/';
        $file .= $name . '.xml';
        //theme config file

        return $config->asXML($file);
    }

    /**
     * get timestamp of last modification of any of the theme's file
     *
     * @param string $theme`
     * @todo cache this
     */
    public static function getLastModified($theme) {
        
        if(!in_array($theme, self::getNameList())) {
            throw new Exception('Theme does not exist: ' . $theme);
        }
        
        $directory = Madoqua_Application::getDataDirectory() . DIRECTORY_SEPARATOR .  'themes/';
        $directory .= $theme . '/';
        //the directory that has the theme

        if (empty(self::$_dirModifieds[$theme])) {
            self::$_dirModifieds[$theme] = (int) self::getDirLastModified(new DirectoryIterator($directory));
            
        }
        return self::$_dirModifieds[$theme];
    }

    /**
     * recursively scan directory for last modified
     *
     * @param string|DirectoryIterator $dir
     * @param int $lastModified
     * @return int
     */
    protected static function getDirLastModified(DirectoryIterator $dir, $lastModified = 0) {
        foreach($dir as $item) {
            if ($item->isDir() && !$item->isDot()) {
                $item = (string) $item->getPath() . DIRECTORY_SEPARATOR . $item->getFilename();
                $lastModified = self::getDirLastModified(new DirectoryIterator($item), $lastModified);
            } elseif ($item->getMTime() > $lastModified) {
                $lastModified = $item->getMTime();
            }
        }
         
        return $lastModified;
    }



}